//+------------------------------------------------------------------+
//|                                                    WavePoint.mqh |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
#ifndef _WAVE_POINT_H
#define _WAVE_POINT_H
#property copyright "Copyright 2023, Warui."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <MyInclude/CommonLog.mqh>

class WavePoint
{
private:
  static const int MAX_CREDIT;
  string m_symbol;
  datetime m_begin_time;
  datetime m_end_time;
  int m_begin_bar_index;
  int m_end_bar_index;
  int m_max_credit;
  ENUM_TIMEFRAMES m_period;
  CommonLog *m_log;

public:
  char getPosition();
  int getCredits();
  void initIndex(string symbol, datetime begin_time, datetime end_time, ENUM_TIMEFRAMES period);
  // WavePoint();
  WavePoint(string symbol, datetime begin_time, datetime end_time, ENUM_TIMEFRAMES period);
  // WavePoint(string symbol, datetime begin_time, datetime end_time, ENUM_TIMEFRAMES period, int max_credit);
  ~WavePoint();
};

static const int WavePoint::MAX_CREDIT = 100;

int WavePoint::getCredits()
{
  int min_ind, max_ind;
  double min, max, credits;
  min_ind = iLowest(m_symbol, m_period, MODE_CLOSE, m_begin_bar_index, m_end_bar_index);
  max_ind = iHighest(m_symbol, m_period, MODE_CLOSE, m_begin_bar_index, m_end_bar_index);
  min = iClose(m_symbol, m_period, min_ind);
  max = iClose(m_symbol, m_period, max_ind);
  double half_diff = (max - min) / 2;
  double middle_price = (max + min) / 2;
  // 右侧价格
  double end_close = iClose(m_symbol, m_period, m_end_bar_index);
  m_log.debug(TimeToString(iTime(m_symbol, m_period, min_ind)) 
    + "min[" + IntegerToString(min_ind) + "]:" + DoubleToString(min) + " max[" + max_ind + "]:" + max);
  m_log.debug("中间价: " + middle_price + ", 当前价: " + DoubleToString(iClose(m_symbol, m_period, 0)));
  // 每分相当于多少points
//  double per_credit_points = (max - min) / (2 * m_max_credit);  // 最大值和最小值之差的1/200, 
//  credits = (end_close - middle_price) / per_credit_points;
  credits = (end_close - middle_price) * m_max_credit / half_diff; 
  return round(credits);
}
//+------------------------------------------------------------------+
char WavePoint::getPosition()
{
  int min_ind, max_ind;
  double min, max, level_points;
  min_ind = iLowest(m_symbol, m_period, MODE_CLOSE, m_begin_bar_index, m_end_bar_index);
  max_ind = iHighest(m_symbol, m_period, MODE_CLOSE, m_begin_bar_index, m_end_bar_index);
  min = iClose(m_symbol, m_period, min_ind);
  max = iClose(m_symbol, m_period, max_ind);
  level_points = (max - min) / 4;
  double end_close = iClose(m_symbol, m_period, m_end_bar_index);
  // printf("%s min[%d]: %f, %s max[%d]: %f", TimeToString(iTime(m_symbol, m_period, min_ind)), min_ind, min, 
  //  TimeToString(iTime(m_symbol, m_period, max_ind)), max_ind, max);
  m_log.debug(TimeToString(iTime(m_symbol, m_period, min_ind)) 
    + "min[" + IntegerToString(min_ind) + "]:" + min + " max[" + max_ind + "]:" + max);
  m_log.debug("中间价: " + (min + max) / 2 + ", 当前价: " + iClose(m_symbol, m_period, 0));
  // printf("中间价: %f, 当前价: %f", (min + max) / 2, iClose(m_symbol, m_period, 0));
  if (min_ind == m_end_bar_index) 
  { // 右侧取到最小值
    return -4;
  } else if (max_ind == m_end_bar_index)
  { // 右侧取到最大值
    return 4;
  }
  if (m_begin_bar_index >= max_ind && max_ind > min_ind && min_ind > m_end_bar_index) 
  {
    if ((min + level_points) >= end_close)
    { // 上升初期
      return 1;
    }
    else if (end_close > (min + level_points) && (min + level_points * 2) >= end_close)
    { // 上升中前期
      return 2;
    }
    else if (end_close > (min + level_points * 2) && (min + level_points * 3) >= end_close)
    { // 上升中后期
      return 3;
    }
    else if (end_close > (min + level_points * 3))
    { // 上升末期
      return 4;
    }
  }
  else if (m_begin_bar_index >= min_ind && min_ind > max_ind && max_ind > m_end_bar_index) 
  {
    if (end_close > (min + level_points * 3))
    { // 下降初期
      return -1;
    }
    else if (end_close > (min + level_points * 2) && (min + level_points * 3) >= end_close)
    { // 下降中前期
      return -2;
    }
    else if (end_close > (min + level_points) && (min + level_points * 2) >= end_close)
    { // 下降中后期
      return -3;
    }
    else if ((min + level_points) >= end_close)
    { // 下降末期
      return -4;
    }
  }
  return 0;
}
// WavePoint::WavePoint()
// {}
WavePoint::WavePoint(string symbol, datetime begin_time, datetime end_time, ENUM_TIMEFRAMES period)
  :m_symbol(symbol), m_begin_time(begin_time), m_end_time(end_time), m_period(period), m_max_credit(MAX_CREDIT)
{
  m_log = new CommonLog(CommonLog::enumLogLevel::INFO);
  initIndex(symbol, begin_time, end_time, period);
}
// WavePoint::WavePoint(string symbol, int begin_bar_index, int end_bar_index, ENUM_TIMEFRAMES period):
//   m_symbol(symbol), m_begin_bar_index(begin_bar_index), m_end_bar_index(end_bar_index), m_period(period)
// {
//   m_begin_time = iTime(symbol, period, begin_bar_index);
//   m_end_time = iTime(symbol, period, end_bar_index);
//   printf("symbol: %s, begin_time: %s, end_time: %s", m_symbol, 
//     TimeToString(m_begin_time, TIME_DATE|TIME_SECONDS), 
//     TimeToString(m_end_time, TIME_DATE|TIME_SECONDS));
// }
//|                                                                  |
// WavePoint::WavePoint(string symbol, datetime begin_time, datetime end_time, 
//   ENUM_TIMEFRAMES period, int max_credit):
//   m_symbol(symbol), m_begin_time(begin_time), m_end_time(end_time),
//   m_period(period), m_max_credit(max_credit)
// {
//   initIndex(symbol, begin_time, end_time, period);
// }

void WavePoint::initIndex(string symbol, datetime begin_time, datetime end_time, ENUM_TIMEFRAMES period)
{
  m_begin_bar_index = iBarShift(symbol, period, begin_time);
  m_end_bar_index = iBarShift(symbol, period, end_time);

  m_log.debug("begin_bar_index: " + m_begin_bar_index + ", end_bar_index: " + m_end_bar_index);
  m_log.debug("symbol: " + m_symbol + ", begin_time: " + TimeToString(begin_time, TIME_DATE|TIME_SECONDS)
    + ", end_time: " + TimeToString(end_time, TIME_DATE|TIME_SECONDS));

}
WavePoint::~WavePoint()
{
}
//+------------------------------------------------------------------+
#endif //_WAVE_POINT_H